if (!Util) {
    var Util = {};
}
Util.DropDownList = function(domEL,onChange, data, oConfig,viewScope){
    this.dom = domEL[0] || domEL;
    this.data = data;
    this.cfg = {
        triggerByClick: false,
        animSlide: false,
        width: $(this.dom).width()||80,
        disable: false,
        actionAtInit: true,
        syncListWidth: true,
        className: '',
        showScrollbar:false,
		ellipsis:false
    };
    $.extend(this.cfg, oConfig);
    this.selectedIndex = 0;
	this.viewScope=viewScope||$(document.body);
    this.onChange = onChange ||function(){};
	this.bMenuHaveReversed=false;
    this.init();
};
Util.DropDownList.CurrentMENU = null;
$(document.body).click(function(e){ // when click the document will hide the menu.
    if (Util.DropDownList.CurrentMENU != null && !Util.contains(Util.DropDownList.CurrentMENU.dom, e.target) && e.target != Util.DropDownList.CurrentMENU.dom) {
        Util.DropDownList.CurrentMENU.hideMenu();
    }
});
Util.DropDownList.prototype = {
    init: function(){
        //create DOM by data
        this.mod = $(document.createElement('div')).addClass('rtq-ddl');
        this.menu = $(document.createElement('ul')).addClass('rtq-ddl-menu');
		this.menuScroll=$(document.createElement('div')).addClass('rtq-ddl-menuScroll').append(this.menu);
        this.menuWrap = $(document.createElement('div')).addClass('rtq-ddl-menuWrap').append(this.menuScroll);
        this.ipt = $('<div class="rtq-ddl-ipt"></div>').attr('readonly', 'readonly');
		if(this.cfg.ellipsis){
			this.menuWrap.addClass('qs-ddl-ellipsis');
			this.ipt.addClass('qs-common-ellipsis');
		}
        this._bindData(this.data);
        $(this.dom).append(this.mod.append(this.ipt).append(this.menuWrap));
        if (this.cfg.showScrollbar) {
            this.scrollpanel = new Util.ScrollPanel(this.menuScroll, {
                showY: true,
                showX: true,
                delayRun: false
            });
        }
        this.mod.css({
            width: this.cfg.width
        }).addClass(this.cfg.className);
        this.ipt.css({
            width: this.cfg.width - 20
        });
        if (this.cfg.disable) {
            this.setDisable(true);
        }
        this._bindEvent();
    },
    _bindEvent:function(){
        //event
        var self = this;
        if(this.cfg.triggerByClick){
            this.mod.bind("click.dropdown",function(e){
				if($(e.target).closest(".rtq-scrollbar").length != 0) return;
                if (self.menuWrap.css('overflow') == 'hidden') {
                    Util.DelayRun('ui_dropdownlist', self.showMenu, 100, self);
                }else {
                    Util.DelayRun('ui_dropdownlist', self.hideMenu, 100, self);
                }
            });
        }else{
            this.mod.bind("mouseover.dropdown",function(e){
                Util.DelayRun('ui_dropdownlist', self.showMenu, 200, self);
            }).bind("mouseout.dropdown",function(e){
                Util.DelayRun('ui_dropdownlist', self.hideMenu, 200, self);
            });
        }
        //this.mod.hover(function(){self.mod.addClass('rtq-ddl-hover');},function(){self.mod.removeClass('rtq-ddl-hover');});
        this.menuScroll.bind("click.dropdown",function(e){
			e.stopPropagation();
            var datael=[],el=$(e.target);
            if (el.closest(".rtq-scrollbar").length == 0&&e.target.tagName.toLowerCase() == 'a') {
                self.selectedIndex = self.menu.children('li').index(el.parent());//in all selectable
                var value=el.attr('value'),count=0;
                datael = self.menu.find("li a[value = '"+value+"']");
                for(var i=0,l=datael.length;i<l;i++){
                    if(datael.get(i)==e.target){
                        break;
                    }else{
                        count++
                    }
                }
                self.menu.find('li a').removeClass('on');
                el.addClass('on');
				
                self._changeValue(self._getTxtByValue(value), value,count);
                self.hideMenu();
            }
        });
        $(document.body).click(function(e){
            if(!Util.contains(self.dom,e.target)&&e.target!=self.dom){
                self.hideMenu();
            }
        });
        if (this.cfg.actionAtInit) {
            this.selectItemByIndex(this.selectedIndex);
        }
        else {
            this.setTextValue(null, this.menu.children('li').eq(this.selectedIndex).children('a').attr('value'));
        }
    },
    showMenu: function(){
        if (this.cfg.disable||!this.menuWrap.hasClass('hideMenu')) {
            return;
        }
        if (Util.DropDownList.CurrentMENU) {
            Util.DropDownList.CurrentMENU.hideMenu();
        }
		//this.cfg.animSlide ? this.menu.slideDown('fast') : this.menu.show();
        if(this.cfg.animSlide){
            this.menuWrap.slideDown('fast');
        }else{
            this.menuWrap.removeClass('hideMenu');
        }
        this.mod.css({
            zIndex: 100
        });
        var position=this._getPostion();
        var style = {
            zIndex: 9999,
            top:position.top,
            left:position.left
        };
        if (this.cfg.syncListWidth) {
            style.width = this.mod.width();
			this.cfg.width =style.width;
        }
        if(this.cfg.showScrollbar){
            this.scrollpanel.reSize(this.cfg.width,position.AvailHeight);
        }
        this.menuWrap.css(style);
        if (this.cfg.ellipsis) {//!jQuery.isSupportTextoverflow
            this.menu.find("li").ellipsis();
        }

        Util.DropDownList.CurrentMENU = this;
    },
	_ellipsis:function(w,h){
		if (this.cfg.ellipsis) {
            this.ipt.ellipsis(false);
        }
	},
    resize:function(w,h){
        var w=w||$(this.dom).width();
        this.cfg.width=w
		
        this.mod.css({
            "width": w
        });
        this.ipt.css({
            "width": w-20
        });
        if(typeof h!='undefined'){
            this.cfg.height=h;
        }
		this._ellipsis();
    },
    _menuReverse:function(aimDirection){
		if(aimDirection==this.bMenuHaveReversed) return;
	 	this.bMenuHaveReversed=aimDirection;
	 	$(this.menu.children().get().reverse()).appendTo(this.menu.empty());
    },
    _getPostion:function(){
        var iptHeight=this.mod.height();
        var modOffset=this.mod.offset();
		var scrollPosition=Util.getScrollPosition();
		var scopeoffset=this.viewScope.offset();
        var realmenuHeight=this.menu.height();
		var modTopHeight=modOffset.top-scrollPosition.scrolly-scopeoffset.top;
        var documentHeight=this.viewScope.height();//$(el).height() dont include padding, but offsetHeight do.
        var downAvailHeight=documentHeight - modTopHeight - iptHeight-12;
		var position={top: iptHeight,left: "-1px"};
		if(this.cfg.showScrollbar){
			//display down
			this._menuReverse(false);
			if(downAvailHeight >= realmenuHeight){
				position.showScroll=false;
				position.AvailHeight =realmenuHeight;
			}else{
				if (typeof this.cfg.height == 'undefined') {
					position.showScroll = true;
					position.AvailHeight = downAvailHeight;
				}
				else {
					position.showScroll = true;
					position.AvailHeight = Math.min(this.cfg.height, downAvailHeight);
				}
			}
		}else{
			if(downAvailHeight >= realmenuHeight){
				//display down
				this._menuReverse(false);
				position.showScroll=false;
				position.AvailHeight=downAvailHeight;
			}else if(modTopHeight >= realmenuHeight){
				//display up
				this._menuReverse(true);
				position.showScroll=false;
				position.AvailHeight =realmenuHeight;
	            position.top = -realmenuHeight;
			}else{
				//display auto adapted
				this._menuReverse(false);
	            position.showScroll=true;
	            position.AvailHeight=downAvailHeight;
			}
		}
		if(position.AvailHeight<30&&position.AvailHeight<realmenuHeight){//display area <40px
            //display up
            this._menuReverse(true);
            if (modTopHeight >= realmenuHeight) {
                position.showScroll = false;
                position.AvailHeight = realmenuHeight;
                position.top = -realmenuHeight;
            }else{
                //display auto adapted
                position.showScroll=true;
                position.AvailHeight=modTopHeight;
				position.top = -modTopHeight;
            }
        }
		return position;
    },
    hideMenu: function(){
        if (this.menu != null) {
            //this.menu.hide();
            this.menuWrap.addClass('hideMenu');
            this.mod.css({
                zIndex: 90
            });
        }
    },
    _changeValue: function(t, v,index){
        this.ipt.html(this._convertSpecialValue(t));
        this.ipt.attr('val', v);
        this.onChange(t, v, index);
		this._ellipsis();
    },
    _bindData: function(data){
        this.clearList();
		var nullIndex=[];
        for (var i = 0, l = data.length; i < l; i++) {
			if (data[i] == null) {
				nullIndex.push(i);
				continue;
			}
            var val =typeof data[i].val == 'undefined' ? data[i].id : data[i].val;
            var item=null;
            if (this.cfg.ellipsis) {//ellipsis
				if(typeof(data[i].title)=="undefined"){
					item=$('<li><a value="' + val + '" href="javascript:void(0)">' + data[i].txt + '</a></li>');
				}else{
					item=$('<li><a value="' + val + '" href="javascript:void(0)" title="' + data[i].title + '">' + data[i].txt + '</a></li>');
				}
            }else if(typeof(data[i].title)=="undefined"){
                item=$('<li><a value="' + val + '" href="javascript:void(0)">' + data[i].txt + '</a></li>');
            }else{
                item=$('<li><a value="' + val + '" href="javascript:void(0)" title="' + data[i].title + '">' + data[i].txt + '</a></li>');
            }
            this.menu.append(item);
        }
		for(var i=0,l=nullIndex.length;i<l;i++){// remove null in data
			data.splice(nullIndex[i],1);
		}
    },
	_getTxtByValue:function(value){
		var data;
		for (var i = 0, l = this.data.length; i < l; i++) {
			data = this.data[i];
			if (data.val == value) {
				return data.txt;
			}
		}
	},
    getValue: function(){
        return this.ipt.attr('val') || '';
    },
    getText: function(){
        return this.ipt.html();
    },
    getSelectedIndex: function(){
        return this.selectedIndex;
    },
    clearList: function(){
        this.menu.html('');
    },
    rebindData: function(data){
		this.data=data;
        this._bindData(this.data);
    },
    insertItem: function(txt, val){
        this.menu.append('<li><a value="' + val + '" href="javascript:void(0)">' + txt + '</a></li>');
		if(!this.bMenuHaveReversed){
			this.data.unshift({txt:txt,val:val});
		}else{
			this.data.push({txt:txt,val:val});
		}
    },
    removeItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().remove();
		for (var i = 0, l = this.data.length; i < l; i++) {
            data = this.data[i];
            if (data.val == value) {
				this.data.splice(i,1);
                return;
            }
        }
    },
    selectItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').click();
    },
    selectItemByIndex: function(idx){
        this.menu.find('li a').eq(idx).click();
    },
	_convertSpecialValue:function(t){
		return t.replace(/&gt;/g, '>').replace(/&lt;/g, '<');
	},
    setTextValue: function(t, v,index){
        if (t) {
            this.ipt.html(this._convertSpecialValue(t));
        }
        if (typeof(v) != "undefined") {
            this.ipt.attr('val', v);
        }
        var el = this.menu.find('li a[value="' + v + '"]');
        if (el.length > 0) {
            el=el.eq(index||0);
            this.ipt.html(this._convertSpecialValue(el.html()));
            this.selectedIndex = this.menu.children('li').index(el.parent());
            this.menu.find('li a').removeClass('on');
            el.addClass('on');            
        }
        this.hideMenu();//updated by Wind 20110527
        this._ellipsis();
    },
    hideItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().hide();
    },
    showItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().show();
    },
    setDisable: function(b){
        this.cfg.disable = (typeof b == 'undefined') ? true : b;
        if (this.cfg.disable) {
            this.mod.addClass('rtq-ddl-disable');
        }
        else {
            this.mod.removeClass('rtq-ddl-disable');
        }
    },
    clearUp: function(){
        //this.mod.remove();
        //this.dom = this.mod = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
    },
    clear: function(){ // 
        this.mod.unbind("click").unbind("mouseout").unbind("mouseover");
        this.menu.unbind("click");
        this.dom = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
        this.mod.remove();
        this.mod = null;
    }
};